package RequestHandlerPackage;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import BusinessLogic.ActionManager;
import BusinessLogic.ActionManager.Action;
import BusinessLogic.CourseManager;
import BusinessLogic.Result;
import BusinessLogic.UserManager;
import DatabasePackage.DatabaseManager;

/**
 *  	   RequestHandler class is a dispatcher that handles requests
 *         received from the view (jsp pages) and dispatches the requests to the
 *         relevant actions located in the ActionManagers
 */
public class RequestHandler {
  private Collection<ActionManager> actionMngs;
  private final DatabaseManager dbMng;
  
  public RequestHandler() throws Exception {
	  dbMng = new DatabaseManager();
      initializeActionManagers();
  }
  
  public RequestHandler(DatabaseManager dbm) {
    dbMng = dbm;
    initializeActionManagers();
  }
  
  /**
   * Initializes the action managers
   */
  private void initializeActionManagers() {
    actionMngs = new ArrayList<ActionManager>();
    actionMngs.add(new UserManager(dbMng));
    actionMngs.add(new CourseManager(dbMng));
  }
  
  /**
   * This constructor is used for testing purposes (allows mocking of
   * DatabaseManager and action managers)
   * 
   * @param dbm
   *          the database manager
   * @param ams
   *          list of action managers
   */
  public RequestHandler(DatabaseManager dbm, List<ActionManager> ams) {
    dbMng = dbm;
    actionMngs = ams;
  }
  
  /**
   * Handles action requests received from the view component by performing the
   * corresponding action from one of the ActionManager classes
   * 
   * @param params
   *          map of parameters received
   * @return a success or failure result object
   */
  public Result handle(Map<String, String[]> params) throws Exception {
    if (!params.containsKey(ActionManager.ActionKey)) {
      return ActionManager.createFailureResult("Error: action parameter is missing in request.");
    }
    String action = params.get(ActionManager.ActionKey)[0];
    for (ActionManager am : actionMngs)
      for (Method m : am.getClass().getDeclaredMethods())
        if (m.isAnnotationPresent(Action.class) && m.getName().equals(action))
          try {
            return (Result) m.invoke(am, params);
          } catch (Exception e) {
            throw new Exception(e.getCause().getMessage(), e.getCause());
          }
    return ActionManager.createFailureResult("Error: the selected action (" + action + ") is not currently supported.");
  }
}
